package kava.framework.lcdui;

import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;

import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.GameCanvas;

public class KavaFrame implements Runnable {

	private static Object formLock = new Object();

	public static int KEYCODE_UP;
	public static int KEYCODE_DOWN;
	public static int KEYCODE_LEFT;
	public static int KEYCODE_RIGHT;
	public static int KEYCODE_FIRE;
	public static int KEYCODE_LEFT_SOFT;
	public static int KEYCODE_RIGHT_SOFT;
	public static int KEYCODE_DELETE;
	public static int KEYCODE_BACK;

	public static int KEYCODE_STAR = 42;
	public static int KEYCODE_POUND = 35;
	public static int KEYCODE_4 = 52;
	public static int KEYCODE_6 = 54;
	public static int KEYCODE_2 = 50;
	public static int KEYCODE_5 = 53;
	public static int KEYCODE_8 = 56;
	public static int KEYCODE_0 = 48;

	private Stack formStack;
	private KavaCanvas canvas;
	private KavaFrameUser kavaUser;
	private int screenWidth;
	private int screenHeight;
	private Graphics graphics;
	private boolean isLaunched;
	private Hashtable strRes;
	private Hashtable configRes;
	private String launchTime;
	private Vector msgQueue;
	private Thread kavaDaemon;
	private boolean isDead;
	private boolean lcdLocked;

	private static KavaFrame singleton = new KavaFrame();

	public static final char MSG_SEP = '#';

	private KavaFrame() {
		formStack = new Stack();
		parseKeyCodes("/kc.txt");
		strRes = ScriptParser.getKeyValuePairs("/str.txt", this.getClass(),
				false);
		configRes = ScriptParser.getKeyValuePairs("/config.txt", this
				.getClass(), true);

		launchTime = (String) configRes.get("launch_time");
		msgQueue = new Vector();
		kavaDaemon = new Thread(this);
		kavaDaemon.start();

	}

	private void parseKeyCodes(String resFile) {
		Hashtable kds = ScriptParser.getKeyValuePairs(resFile, this.getClass(),
				true);

		KEYCODE_UP = Integer.parseInt((String) kds.get("KEYCODE_UP"));
		KEYCODE_DOWN = Integer.parseInt((String) kds.get("KEYCODE_DOWN"));
		KEYCODE_LEFT = Integer.parseInt((String) kds.get("KEYCODE_LEFT"));
		KEYCODE_RIGHT = Integer.parseInt((String) kds.get("KEYCODE_RIGHT"));
		KEYCODE_FIRE = Integer.parseInt((String) kds.get("KEYCODE_FIRE"));
		KEYCODE_LEFT_SOFT = Integer.parseInt((String) kds
				.get("KEYCODE_LEFT_SOFT"));
		KEYCODE_RIGHT_SOFT = Integer.parseInt((String) kds
				.get("KEYCODE_RIGHT_SOFT"));
		KEYCODE_DELETE = Integer.parseInt((String) kds.get("KEYCODE_DELETE"));
		KEYCODE_BACK = Integer.parseInt((String) kds.get("KEYCODE_BACK"));

		KEYCODE_STAR = Integer.parseInt((String) kds.get("KEYCODE_STAR"));
		KEYCODE_POUND = Integer.parseInt((String) kds.get("KEYCODE_POUND"));
		KEYCODE_4 = Integer.parseInt((String) kds.get("KEYCODE_4"));
		KEYCODE_6 = Integer.parseInt((String) kds.get("KEYCODE_6"));
		KEYCODE_2 = Integer.parseInt((String) kds.get("KEYCODE_2"));
		KEYCODE_5 = Integer.parseInt((String) kds.get("KEYCODE_5"));
		KEYCODE_8 = Integer.parseInt((String) kds.get("KEYCODE_8"));
		KEYCODE_0 = Integer.parseInt((String) kds.get("KEYCODE_0"));
	}

	public static boolean isEmpty() {
		return singleton.formStack.empty();
	}

	public static Form peek() {
		return (Form) singleton.formStack.peek();
	}

	public static void push(Form form) {
		synchronized (formLock) {
			if (form != null) {
				if (!singleton.formStack.empty()) {
					Form topForm = (Form) singleton.formStack.peek();
					topForm.onDeactive();
				}
				singleton.formStack.push(form);
				form.onActive();
				KavaFrame.updateScrean();
			}
		}
	}

	public static void pop() {
		synchronized (formLock) {
			if (!singleton.formStack.empty()) {
				Form topForm = (Form) singleton.formStack.peek();
				topForm.onDeactive();
				singleton.formStack.pop();
				if (!singleton.formStack.empty()) {
					topForm = (Form) singleton.formStack.peek();
					topForm.onActive();
				}
				KavaFrame.updateScrean();
			}
		}

	}

	// public static void debugMsgQueue(){
	// for(int i = 0 ;i < singleton.msgQueue.size() ;i++ ){
	// Util.debug("KavaFrame.debugMsgQueue", singleton.msgQueue.elementAt(i));
	// }
	// }

	public static Form getFormByTitle(String title) {
		for (int i = 0; i < singleton.formStack.size(); i++) {
			Form form = (Form) singleton.formStack.elementAt(i);
			if (form.title.equals(title)) {
				return form;
			}
		}
		return null;
	}

	public static String getTopFormTitle() {
		return peek().title;
	}

	public static boolean containFormByTitle(String title) {
		for (int i = 0; i < singleton.formStack.size(); i++) {
			Form form = (Form) singleton.formStack.elementAt(i);
			if (form.title.equals(title)) {
				return true;
			}
		}
		return false;
	}

	public static boolean isTheFrontestForm(Form f) {
		return KavaFrame.peek() == f;
	}

	public static int getScreenWidth() {
		return singleton.screenWidth;
	}

	public static int getScreenHeight() {
		return singleton.screenHeight;
	}

	public static Canvas getCanvas() {
		if (singleton.canvas == null) {
			singleton.canvas = singleton.new KavaCanvas();
		}
		return singleton.canvas;
	}

	public static boolean hasPointerEvents() {
		return singleton.canvas.hasPointerEvents();
	}

	public static int getGameAction(int keyCode) {
		return singleton.canvas.getGameAction(keyCode);
	}

	public static void setKavaUser(KavaFrameUser user) {
		if (singleton.kavaUser == null) {
			singleton.kavaUser = user;
		}
	}

	public static KavaFrameUser getLauncher() {
		return singleton.kavaUser;
	}

	public static void updateScrean() {
		singleton.paintTopForm();
		singleton.canvas.flushGraphics();
	}

	public static void resetClip(Graphics g) {
		g
				.setClip(0, 0, KavaFrame.getScreenWidth(), KavaFrame
						.getScreenHeight());
	}

	public static int numAlphaLevels() {
		return singleton.kavaUser.numAlphaLevels();
	}

	public static Hashtable configRes() {
		return singleton.configRes;
	}

	public static Hashtable strRes() {
		return singleton.strRes;
	}

	public static Graphics getGraphics() {
		if (singleton.lcdLocked) {
			return null;
		} else {
			singleton.lcdLocked = true;
			return singleton.graphics;
		}
	}

	public static void freeGraphics() {
		singleton.lcdLocked = false;
	}

	public static void addAppMessage(int msgCode, String msg) {
		String s = "" + msgCode + MSG_SEP + msg;
		singleton.msgQueue.addElement(s);
	}

	public static boolean isKavaFrameShow() {
		return singleton.canvas.isShown();
	}

	public void run() {
		while (!isDead) {
			if (!msgQueue.isEmpty() && KavaFrame.isKavaFrameShow()) {
				String msg = (String) msgQueue.firstElement();
				int pos = msg.indexOf(KavaFrame.MSG_SEP);
				kavaUser.handleAppMessage(Integer.parseInt(msg
						.substring(0, pos)), msg.substring(pos + 1));
				msgQueue.removeElementAt(0);

				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

	public static void destroy() {
		if (singleton.isDead == false) {
			singleton.isDead = true;
			try {
				singleton.kavaDaemon.join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			singleton.kavaDaemon = null;
			while (!KavaFrame.isEmpty()) {
				KavaFrame.pop();
			}
			System.gc();
		}
	}

	final void keyPressed(int keyCode) {
		if (!singleton.isDead && !isEmpty()) {
			Form topForm = peek();
			topForm.onKeyPressed(keyCode);
		}
	}

	final void keyReleased(int keyCode) {
		if (!isEmpty() && !singleton.isDead) {
			Form topForm = peek();
			topForm.onKeyReleased(keyCode);
		}

	}

	final void keyRepeated(int keyCode) {
		if (!isEmpty() && !singleton.isDead) {
			Form topForm = peek();
			topForm.onKeyRepeat(keyCode);
		}

	}

	private void paintTopForm() {

		if (!KavaFrame.isEmpty()) {
			Form topForm = KavaFrame.peek();
			Graphics g = getGraphics();
			if (g != null) {
				topForm.paint(g);
				KavaFrame.freeGraphics();
			}

		}

	}

	final void pointerPressed(int x, int y) {
		if (!isEmpty() && !singleton.isDead) {
			Form topForm = peek();
			topForm.onPenDown(x, y);
		}
	}

	final void pointerDraged(int x, int y) {
		if (!isEmpty() && !singleton.isDead) {
			Form topForm = peek();
			topForm.onPenMove(x, y);
		}
	}

	final void pointerReleased(int x, int y) {
		if (!isEmpty() && !singleton.isDead) {
			Form topForm = peek();
			topForm.onPenUp(x, y);
		}
	}

	final void hideNotify() {
		if (!isEmpty()) {
			Form topForm = peek();
			topForm.onDeactive();
		}

	}

	final void showNotify() {
		if (!isEmpty()) {
			Form topForm = peek();
			topForm.onActive();
			KavaFrame.updateScrean();
		}
	}

	public static final void invalideRec(int x, int y, int width, int height) {
		// singleton.canvas.flushGraphics();
		// originally ,use flushGraphics(x, y, width, height);,but moto bug
		singleton.canvas.repaint(x, y, width, height);
	}

	public String getLaunchTime() {
		return launchTime;
	}

	public void setLaunchTime(String launchTime) {
		this.launchTime = launchTime;
	}

	// inner canvas

	class KavaCanvas extends GameCanvas {

		KavaCanvas() {
			super(false);
			this.setFullScreenMode(true);
			KavaFrame.this.screenWidth = this.getWidth();
			KavaFrame.this.screenHeight = this.getHeight();
			KavaFrame.this.graphics = this.getGraphics();
		}

		protected void showNotify() {
			// this.setFullScreenMode(true);
			if (KavaFrame.this.isLaunched == false) {
				if (getLaunchTime().equals("FIRST_SHOW")) {
					KavaFrame.getLauncher().launch();
					KavaFrame.this.isLaunched = true;
				}
			} else {
				KavaFrame.this.showNotify();
			}
		}

		protected void hideNotify() {
			KavaFrame.this.hideNotify();
		}

		protected void keyPressed(int keyCode) {

			KavaFrame.this.keyPressed(keyCode);
		}

		protected void keyReleased(int keyCode) {
			KavaFrame.this.keyReleased(keyCode);
		}

		protected void keyRepeated(int keyCode) {
			KavaFrame.this.keyRepeated(keyCode);
		}

		protected void pointerDragged(int x, int y) {

			KavaFrame.this.pointerDraged(x, y);
		}

		protected void pointerPressed(int x, int y) {

			KavaFrame.this.pointerPressed(x, y);
		}

		protected void pointerReleased(int x, int y) {

			KavaFrame.this.pointerReleased(x, y);
		}

		protected void sizeChanged(int w, int h) {
			KavaFrame.this.screenHeight = h;
			KavaFrame.this.screenWidth = w;

			if (KavaFrame.this.isLaunched == false) {
				if (KavaFrame.this.getLaunchTime().equals("FIRST_SIZECHANGE")) {
					KavaFrame.getLauncher().launch();
					KavaFrame.this.isLaunched = true;
				}

			}
		}
	}

}
